<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Detection of Diamond Markers</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li><li class="navelem"><a class="el" href="../../d9/d6d/tutorial_table_of_content_aruco.html">ArUco marker detection (aruco module)</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Detection of Diamond Markers </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>A ChArUco diamond marker (or simply diamond marker) is a chessboard composed by 3x3 squares and 4 ArUco markers inside the white squares. It is similar to a ChArUco board in appearance, however they are conceptually different.</p>
<div class="image">
<img src="../../diamondmarkers.png" alt="diamondmarkers.png"/>
<div class="caption">
Diamond marker examples</div></div>
<p> In both, ChArUco board and Diamond markers, their detection is based on the previous detected ArUco markers. In the ChArUco case, the used markers are selected by directly looking their identifiers. This means that if a marker (included in the board) is found on a image, it will be automatically assumed to belong to the board. Furthermore, if a marker board is found more than once in the image, it will produce an ambiguity since the system wont be able to know which one should be used for the Board.</p>
<p>On the other hand, the detection of Diamond marker is not based on the identifiers. Instead, their detection is based on the relative position of the markers. As a consequence, marker identifiers can be repeated in the same diamond or among different diamonds, and they can be detected simultaneously without ambiguity. However, due to the complexity of finding marker based on their relative position, the diamond markers are limited to a size of 3x3 squares and 4 markers.</p>
<p>As in a single ArUco marker, each Diamond marker is composed by 4 corners and a identifier. The four corners correspond to the 4 chessboard corners in the marker and the identifier is actually an array of 4 numbers, which are the identifiers of the four ArUco markers inside the diamond.</p>
<p>Diamond markers are useful in those scenarios where repeated markers should be allowed. For instance:</p>
<ul>
<li>To increase the number of identifiers of single markers by using diamond marker for labeling. They would allow up to N^4 different ids, being N the number of markers in the used dictionary.</li>
<li>Give to each of the four markers a conceptual meaning. For instance, one of the four marker ids could be used to indicate the scale of the marker (i.e. the size of the square), so that the same diamond can be found in the environment with different sizes just by changing one of the four markers and the user does not need to manually indicate the scale of each of them. This case is included in the <code>diamond_detector.cpp</code> file inside the samples folder of the module.</li>
</ul>
<p>Furthermore, as its corners are chessboard corners, they can be used for accurate pose estimation.</p>
<p>The diamond functionalities are included in <code>&lt;<a class="el" href="../../da/d3b/charuco_8hpp.html">opencv2/aruco/charuco.hpp</a>&gt;</code></p>
<h2>ChArUco Diamond Creation </h2>
<p>The image of a diamond marker can be easily created using the <code><a class="el" href="../../d9/d6a/group__aruco.html#gaf71fb897d5f03f7424c0c84715aa6228" title="Draw a ChArUco Diamond marker. ">drawCharucoDiamond()</a></code> function. For instance:</p>
<div class="fragment"><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> diamondImage;</div><div class="line"><a class="code" href="../../dc/d84/group__core__basic.html#ga6395ca871a678020c4a31fadf7e8cc63">cv::Ptr&lt;cv::aruco::Dictionary&gt;</a> dictionary = <a class="code" href="../../d9/d6a/group__aruco.html#gaf5d7e909fe8ff2ad2108e354669ecd17">cv::aruco::getPredefinedDictionary</a>(<a class="code" href="../../d9/d6a/group__aruco.html#ggac84398a9ed9dd01306592dd616c2c975a6eb1a3e9c94c7123d8b1904a57193f16">cv::aruco::DICT_6X6_250</a>);</div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#gaf71fb897d5f03f7424c0c84715aa6228">cv::aruco::drawCharucoDiamond</a>(dictionary, <a class="code" href="../../d6/dcf/classcv_1_1Vec.html">cv::Vec4i</a>(45,68,28,74), 200, 120, markerImage);</div></div><!-- fragment --><p>This will create a diamond marker image with a square size of 200 pixels and a marker size of 120 pixels. The marker ids are given in the second parameter as a <code>Vec4i</code> object. The order of the marker ids in the diamond layout are the same as in a standard ChArUco board, i.e. top, left, right and bottom.</p>
<p>The image produced will be:</p>
<div class="image">
<img src="../../diamondmarker.png" alt="diamondmarker.png"/>
<div class="caption">
Diamond marker</div></div>
<p> A full working example is included in the <code>create_diamond.cpp</code> inside the module samples folder.</p>
<p>Note: The samples now take input via commandline via the <a href="http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0">OpenCV Commandline Parser</a>. For this file the example parameters will look like </p><div class="fragment"><div class="line"><span class="stringliteral">&quot;_path_/mydiamond.png&quot;</span> -sl=200 -ml=120 -d=10 -ids=45,68,28,74</div></div><!-- fragment --><h2>ChArUco Diamond Detection </h2>
<p>As in most cases, the detection of diamond markers requires a previous detection of ArUco markers. After detecting markers, diamond are detected using the <code><a class="el" href="../../d9/d6a/group__aruco.html#gaade474aa951d02470c34ddbb91d851ea" title="Detect ChArUco Diamond markers. ">detectCharucoDiamond()</a></code> function:</p>
<div class="fragment"><div class="line"><a class="code" href="../../d3/d63/classcv_1_1Mat.html">cv::Mat</a> inputImage;</div><div class="line"><span class="keywordtype">float</span> squareLength = 0.40;</div><div class="line"><span class="keywordtype">float</span> markerLength = 0.25;</div><div class="line">...</div><div class="line"></div><div class="line"></div><div class="line">std::vector&lt;<span class="keywordtype">int</span>&gt; markerIds;</div><div class="line">std::vector&lt;std::vector&lt; cv::Point2f&gt;&gt; markerCorners;</div><div class="line"></div><div class="line"><span class="comment">// detect ArUco markers</span></div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#gab9159aa69250d8d3642593e508cb6baa">cv::aruco::detectMarkers</a>(inputImage, dictionary, markerCorners, markerIds);</div><div class="line"></div><div class="line">std::vector&lt;cv::Vec4i&gt; diamondIds;</div><div class="line">std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt; diamondCorners;</div><div class="line"></div><div class="line"><span class="comment">// detect diamon diamonds</span></div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#gaade474aa951d02470c34ddbb91d851ea">cv::aruco::detectCharucoDiamond</a>(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds);</div></div><!-- fragment --><p>The <code><a class="el" href="../../d9/d6a/group__aruco.html#gaade474aa951d02470c34ddbb91d851ea" title="Detect ChArUco Diamond markers. ">detectCharucoDiamond()</a></code> function receives the original image and the previous detected marker corners and ids. The input image is necessary to perform subpixel refinement in the ChArUco corners. It also receives the rate between the square size and the marker sizes which is required for both, detecting the diamond from the relative positions of the markers and interpolating the ChArUco corners.</p>
<p>The function returns the detected diamonds in two parameters. The first parameter, <code>diamondCorners</code>, is an array containing all the four corners of each detected diamond. Its format is similar to the detected corners by the <code><a class="el" href="../../d9/d6a/group__aruco.html#gab9159aa69250d8d3642593e508cb6baa" title="Basic marker detection. ">detectMarkers()</a></code> function and, for each diamond, the corners are represented in the same order than in the ArUco markers, i.e. clockwise order starting with the top-left corner. The second returned parameter, <code>diamondIds</code>, contains all the ids of the returned diamond corners in <code>diamondCorners</code>. Each id is actually an array of 4 integers that can be represented with <code>Vec4i</code>.</p>
<p>The detected diamond can be visualized using the function <code><a class="el" href="../../d9/d6a/group__aruco.html#ga0dbf27203267fb8e9f282554cf0d3433" title="Draw a set of detected ChArUco Diamond markers. ">drawDetectedDiamonds()</a></code> which simply receives the image and the diamond corners and ids:</p>
<div class="fragment"><div class="line">...</div><div class="line">std::vector&lt;<a class="code" href="../../d6/dcf/classcv_1_1Vec.html">cv::Vec4i</a>&gt; diamondIds;</div><div class="line">std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt; diamondCorners;</div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#gaade474aa951d02470c34ddbb91d851ea">cv::aruco::detectCharucoDiamond</a>(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds);</div><div class="line"></div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#ga0dbf27203267fb8e9f282554cf0d3433">cv::aruco::drawDetectedDiamonds</a>(inputImage, diamondCorners, diamondIds);</div></div><!-- fragment --><p>The result is the same that the one produced by <code><a class="el" href="../../d9/d6a/group__aruco.html#ga2ad34b0f277edebb6a132d3069ed2909" title="Draw detected markers in image. ">drawDetectedMarkers()</a></code>, but printing the four ids of the diamond:</p>
<div class="image">
<img src="../../detecteddiamonds.png" alt="detecteddiamonds.png"/>
<div class="caption">
Detected diamond markers</div></div>
<p> A full working example is included in the <code>detect_diamonds.cpp</code> inside the module samples folder.</p>
<p>Note: The samples now take input via commandline via the <a href="http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0">OpenCV Commandline Parser</a>. For this file the example parameters will look like </p><div class="fragment"><div class="line">-c=<span class="stringliteral">&quot;_path_/calib.txt&quot;</span> -dp=<span class="stringliteral">&quot;_path_/detector_params.yml&quot;</span> -sl=0.04 -ml=0.02 -d=10</div></div><!-- fragment --><h2>ChArUco Diamond Pose Estimation </h2>
<p>Since a ChArUco diamond is represented by its four corners, its pose can be estimated in the same way than in a single ArUco marker, i.e. using the <code><a class="el" href="../../d9/d6a/group__aruco.html#ga84dd2e88f3e8c3255eb78e0f79571bd1" title="Pose estimation for single markers. ">estimatePoseSingleMarkers()</a></code> function. For instance:</p>
<div class="fragment"><div class="line">...</div><div class="line"></div><div class="line">std::vector&lt;<a class="code" href="../../d6/dcf/classcv_1_1Vec.html">cv::Vec4i</a>&gt; diamondIds;</div><div class="line">std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt; diamondCorners;</div><div class="line"></div><div class="line"><span class="comment">// detect diamon diamonds</span></div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#gaade474aa951d02470c34ddbb91d851ea">cv::aruco::detectCharucoDiamond</a>(inputImage, markerCorners, markerIds, squareLength / markerLength, diamondCorners, diamondIds);</div><div class="line"></div><div class="line"><span class="comment">// estimate poses</span></div><div class="line">std::vector&lt;cv::Vec3d&gt; rvecs, tvecs;</div><div class="line"><a class="code" href="../../d9/d6a/group__aruco.html#ga84dd2e88f3e8c3255eb78e0f79571bd1">cv::aruco::estimatePoseSingleMarkers</a>(diamondCorners, squareLength, camMatrix, distCoeffs, rvecs, tvecs);</div><div class="line"></div><div class="line"><span class="comment">// draw axis</span></div><div class="line"><span class="keywordflow">for</span>(<span class="keywordtype">unsigned</span> <span class="keywordtype">int</span> i=0; i&lt;rvecs.size(); i++)</div><div class="line">    <a class="code" href="../../d9/d6a/group__aruco.html#ga16fda651a4e6a8f5747a85cbb6b400a2">cv::aruco::drawAxis</a>(inputImage, camMatrix, distCoeffs, rvecs[i], tvecs[i], axisLength);</div></div><!-- fragment --><p>The function will obtain the rotation and translation vector for each of the diamond marker and store them in <code>rvecs</code> and <code>tvecs</code>. Note that the diamond corners are a chessboard square corners and thus, the square length has to be provided for pose estimation, and not the marker length. Camera calibration parameters are also required.</p>
<p>Finally, an axis can be drawn to check the estimated pose is correct using <code><a class="el" href="../../d9/d6a/group__aruco.html#ga16fda651a4e6a8f5747a85cbb6b400a2" title="Draw coordinate system axis from pose estimation. ">drawAxis()</a></code>:</p>
<div class="image">
<img src="../../diamondsaxis.png" alt="diamondsaxis.png"/>
<div class="caption">
Detected diamond axis</div></div>
<p> The coordinate system of the diamond pose will be in the center of the marker with the Z axis pointing out, as in a simple ArUco marker pose estimation.</p>
<p>Sample video:</p>
<p> 
<iframe width="420" height="315" src="https://www.youtube.com/embed/OqKpBnglH7k" frameborder="0" allowfullscreen></iframe>
</p>
<p>A full working example is included in the <code>detect_diamonds.cpp</code> inside the module samples folder.</p>
<p>Note: The samples now take input via commandline via the <a href="http://docs.opencv.org/trunk/d0/d2e/classcv_1_1CommandLineParser.html#gsc.tab=0">OpenCV Commandline Parser</a>. For this file the example parameters will look like </p><div class="fragment"><div class="line">-c=<span class="stringliteral">&quot;_output path_/calib.txt&quot;</span> -dp=<span class="stringliteral">&quot;_path_/detector_params.yml&quot;</span> -sl=0.04 -ml=0.02 -d=10</div></div><!-- fragment --> </div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:38 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
